<template>
    <div class="w-full h-full overflow-hidden grid grid-cols-5">
        <!-- 侧边栏 -->
        <div class="col-span-1 p-4 w-full h-full bg-[#35355f33] flex flex-col gap-4 overflow-hidden">
            <!-- 额度 -->
            <div class="grid bg-[#35355f55] text-white grid-cols-2 gap-4 p-4 rounded text-base font-bold">
                <div class="flex col-span-1">
                    <p>个人额度:</p>
                    <p>{{ amount.public }}</p>
                </div>
                <div class="flex col-span-1">
                    <p>共用额度:</p>
                    <p>{{ amount.public }}</p>
                </div>
            </div>
            <!-- gpt选择器 -->
            <ElSelect v-model="selectGpt" placeholder="请选择GPT模型" size="large">
                <ElOption v-for="item in gptList" :key="item.id" :value="item.id" :label="item.name"></ElOption>
            </ElSelect>
            <!-- 对话列表 -->
            <Conversations :itemsStyle="{ backgroundColor: '#ffffffaa' }" 
            :itemsHoverStyle="{ backgroundColor: '#ffffffee' }"
            :itemsActiveStyle="{ backgroundColor: '#ffffffff' }" 
            class="flex-1 !w-full [&>*]:!w-full"
                v-model:active="activeChat" :items="chatList" :show-tooltip="true" row-key="key"
                tooltip-placement="right" :tooltip-offset="35" show-to-top-btn showBuiltInMenu
                show-built-in-menu-type="always">
                <template #menu="{ item }">
                    <div class="flex flex-col">
                        <ElButton @click="delectChatList(item.key)">
                            <ElIcon>
                                <component :is="Delete" />
                            </ElIcon>
                            删除
                        </ElButton>
                        <ElButton class="!m-0" @click="clearChatList(item.key)">
                            <ElIcon>
                                <component :is="Delete" />
                            </ElIcon>
                            清空
                        </ElButton>
                    </div>
                </template>
            </Conversations>
            <!-- 新建对话按钮 -->
            <ElButton size="large" @click="createChatList">新的对话</ElButton>
        </div>
        <!-- 内容栏 -->
        <div style="display: grid;grid-template-rows: 1fr auto;" class=" overflow-hidden col-span-4 p-4 gap-4 h-full">
            <BubbleList ref="bubbleListRef" @scroll="scrollEvent" style="max-height: none;" :list="chatHistory" />
            <Sender v-model="userInput" :auto-size="{ minRows: 2, maxRows: 5 }" @submit="sendMessage" />
        </div>
    </div>

    <ElDialog v-model="dialog.flag" :title="dialog.title" align-center width="400px" @confirm="createChatList">
        <div class="flex flex-col gap-2">
            <ElInput v-model="dialog.input" :placeholder="dialog.title" />
            <div class="w-full flex gap-2 items-end justify-end">
                <ElButton type="default" @click="dialog.cancel">取消</ElButton>
                <ElButton type="primary" @click="dialog.confirm">确定</ElButton>
            </div>
        </div>
    </ElDialog>
</template>

<script setup lang='ts' name=''>
import { Delete } from '@element-plus/icons-vue';
import { ElMessage, ElSelect, ElButton, ElOption, ElIcon, ElDialog, ElInput } from 'element-plus';
import { Conversations, Sender, BubbleList } from 'vue-element-plus-x';
import { onMounted, ref, watch } from 'vue';
import type { ConversationItem } from 'vue-element-plus-x/types/Conversations';

import {
    getGptList, getPublicLimit, getQuota,
    getChatList, delChatList, getChatRecord,
    chat,
    creChatList,
    clearChatRecord
} from '@/api/chat';
/** 通用单对话框封装 */
const dialog = ref({
    flag: false,
    title: '',
    input: '',
    confirm: async () => { await dialog.value.fun(dialog.value.input); dialog.value.cancel() },
    cancel: () => {
        dialog.value.flag = false,
            dialog.value.input = '',
            dialog.value.title = '',
            dialog.value.confirm = async () => { await dialog.value.fun(dialog.value.input); dialog.value.cancel() }
    },
    fun: (input: string): any => { }
})
/** 对话框方法 */
function showDialog(title: string, fun: (input: string) => any) {
    dialog.value.input = ''
    dialog.value.title = title
    dialog.value.fun = fun
    dialog.value.flag = true
}

/** GPT列表 */
const selectGpt = ref<number>(0)
const gptList = ref<any>([])

/** 额度 */
const amount = ref({
    public: 0,
    private: 0
})
/** 第一次加载聊天记录 */
const firstLoad = ref(true)

/** 对话列表 */
const activeChat = ref<number>(0)
const chatList = ref<any>([])

/** 用户输入 */
const userInput = ref('')

/** 聊天记录 */
const chatHistory = ref<any>([])
const isEnd = ref(false)
const chatConfig = ref({
    page: 0,
    size: 20
})
const chatId = ref(0)
const bubbleListRef = ref<any>(null)


/** 刷新额度 */
function getAmount() {
    getPublicLimit().then(res => {
        amount.value.public = res.data
    })
    getQuota().then(res => {
        amount.value.private = res.data
    })
}


/** 对话列表->加载 */
async function loadChatList() {
    const res = await getChatList()
    if ((JSON.stringify(res)) == "{}") {
        await creChatList("新对话")
        await loadChatList()
    }
    chatList.value = []
    res.data.forEach((item: any) => {
        chatList.value.push({
            key: item.id,
            label: item.name
        })
    });
}


/** 对话列表->删除 */
function delectChatList(key: number) {
    delChatList(key).then(async (res) => {
        ElMessage.success('删除成功')
        await loadChatList()
        activeChat.value = chatList.value.length > 0 ? chatList.value[0].key : -1
    })
}


/** 对话列表->清空 */
function clearChatList(key: number) {
    clearChatRecord(key).then(async (res) => {
        ElMessage.success('清空成功')
        await loadChatList()
        activeChat.value = chatList.value.length > 0 ? chatList.value[0].key : -1
    })
}


/** 对话列表->新增 */
function createChatList() {
    showDialog('请输入对话名称', (input: string) => {
        creChatList(input).then(() => {
            loadChatList()
            ElMessage.success('创建成功')
        })
    })
}


/** 聊天记录->加载 */
function loadChatRecord() {
    getChatRecord(activeChat.value, chatConfig.value.page, chatConfig.value.size).then(res => {
        if (JSON.stringify(res) != "{}") {
            const list: any = []
            res.data.forEach((item: any) => {
                chatId.value += 1
                chatHistory.value.unshift
                    ({
                        key: chatId.value, // 唯一标识
                        role: item.identity == 1 ? "user" : "ai", // user | ai 自行更据模型定义
                        placement: item.identity == 1 ? "end" : "start", // start | end 气泡位置
                        content: item.content, // 消息内容 流式接受的时候，只需要改这个值即可，这里暂时没有用到流式数据
                        // loading, // 当前气泡的加载状态
                        // shape, // 气泡的形状
                        // variant, // 气泡的样式
                        isMarkdown: true, // 是否渲染为 markdown
                        // typing, // 是否开启打字器效果 该属性不会和流式接受冲突
                        // isFog: role === 'ai', // 是否开启打字雾化效果，该效果 v1.1.6 新增，且在 typing 为 true 时生效，该效果会覆盖 typing 的 suffix 属性
                        avatar: item.identity == 1 ? "" : "/image/avatar.png",
                        avatarSize: item.identity == 1 ? "" : '48px',
                        avatarGap: '12px'
                    })
            });
            firstLoad.value = false
            bubbleListRef.value.scrollToBubble(chatId.value - chatConfig.value.page)
            console.log(chatHistory.value)
        } else {
            isEnd.value = true
        }
    })
}


/** 发送消息 */
function sendMessage() {
    chatHistory.value.push({
        key: chatHistory.value.length + 1,
        role: 'user',
        placement: 'end',
        content: userInput.value,
    })
    chat(activeChat.value, userInput.value, selectGpt.value).then(res => {
    })
    userInput.value = ''
}


/** 滚动到顶部 */
const scrollEvent = (event: Event) => {
    const target = event.target as HTMLElement
    if (chatHistory.value.length >= 20 && target.scrollTop == 0 && !firstLoad.value && !isEnd.value) {
        chatConfig.value.page += 20
        chatConfig.value.size += 20
        loadChatRecord()
    }
}


/** 监听对话切换 */
watch(() => activeChat.value, () => {
    chatHistory.value = [];
    chatConfig.value.page = 0
    chatConfig.value.size = 20
    firstLoad.value = true
    chatId.value = 0
    loadChatRecord()
})


/** 自动加载数据 */
onMounted(async () => {
    /** 获取GPT列表 */
    getGptList().then(res => {
        gptList.value = res.data
        selectGpt.value = res.data[0].id
    })
    /** 获取额度 */
    getAmount()
    /** 获取对话列表 */
    await loadChatList()
    activeChat.value = chatList.value.length > 0 ? chatList.value[0].key : -1
})
</script>

<style scoped>
:deep(.conversations-list) {
    background: #4494ad13 !important;
}

/* 直接针对暗黑模式设置样式 */
:deep(.dark .conversation-item .conversation-label) {
    color: white !important;
}

:deep(.dark .conversations-list) {
    background: rgba(68, 148, 173, 0.2) !important;
}

/* 如果上面的不生效，尝试这个更具体的选择器 */
:deep(html.dark .conversations-list) {
    background: rgba(68, 148, 173, 0.2) !important;
}

:deep(html.dark .conversation-item .conversation-label) {
    color: white !important;
}
</style>